/**
 * 简化版 MP4 Faststart 优化
 * 使用基础的 atom 重排序方法，不依赖 mp4-muxer
 */

/**
 * 简单的 MP4 Faststart 优化
 * @param {File} file - 原始 MP4 文件
 * @param {Function} onProgress - 进度回调
 * @returns {Promise<File>} 优化后的文件
 */
export async function optimizeMP4Simple(file, onProgress = () => {}) {
    console.log('🚀 开始简单 MP4 Faststart 优化...')
    onProgress(0, '开始读取文件')

    try {
        // 1. 读取文件
        onProgress(10, '正在读取文件')
        const arrayBuffer = await file.arrayBuffer()
        const uint8Array = new Uint8Array(arrayBuffer)
        
        // 2. 解析 atoms
        onProgress(30, '正在解析 MP4 结构')
        const atoms = parseAtoms(uint8Array)
        
        console.log('找到的 atoms:', atoms.map(a => `${a.type}(${a.size})`).join(' -> '))
        
        // 3. 检查是否需要优化
        const ftypIndex = atoms.findIndex(a => a.type === 'ftyp')
        const moovIndex = atoms.findIndex(a => a.type === 'moov')
        const mdatIndex = atoms.findIndex(a => a.type === 'mdat')
        
        if (ftypIndex === -1 || moovIndex === -1) {
            throw new Error('无效的 MP4 文件：缺少必要的 atoms')
        }
        
        if (moovIndex < mdatIndex && mdatIndex !== -1) {
            console.log('✓ 文件已经是 faststart 格式')
            onProgress(100, '文件已经优化')
            return file
        }
        
        // 4. 重排序
        onProgress(50, '正在重排序')
        const optimizedBuffer = reorderAtoms(atoms, uint8Array)
        
        // 5. 创建新文件
        onProgress(90, '正在生成文件')
        const optimizedBlob = new Blob([optimizedBuffer], { type: 'video/mp4' })
        const optimizedFile = new File(
            [optimizedBlob],
            file.name.replace('.mp4', '_faststart.mp4'),
            { type: 'video/mp4' }
        )
        
        onProgress(100, '优化完成')
        console.log('✅ 优化完成')
        
        return optimizedFile
        
    } catch (error) {
        console.error('❌ 优化失败:', error)
        throw error
    }
}

/**
 * 解析 MP4 atoms
 */
function parseAtoms(buffer) {
    const atoms = []
    let offset = 0

    while (offset < buffer.length - 8) {
        const size = ((buffer[offset] & 0xFF) << 24) | 
                     ((buffer[offset + 1] & 0xFF) << 16) | 
                     ((buffer[offset + 2] & 0xFF) << 8) | 
                     (buffer[offset + 3] & 0xFF)
        
        const type = String.fromCharCode(
            buffer[offset + 4],
            buffer[offset + 5],
            buffer[offset + 6],
            buffer[offset + 7]
        )

        if (size === 0) {
            const remainingSize = buffer.length - offset
            atoms.push({
                type,
                offset,
                size: remainingSize,
                data: buffer.slice(offset, buffer.length)
            })
            break
        } else if (size < 8 || offset + size > buffer.length) {
            console.warn(`无效的 atom: ${type}, size: ${size}, offset: ${offset}`)
            break
        } else {
            atoms.push({
                type,
                offset,
                size,
                data: buffer.slice(offset, offset + size)
            })
            offset += size
        }
    }

    return atoms
}

/**
 * 重排序 atoms
 */
function reorderAtoms(atoms, originalBuffer) {
    const ftypAtom = atoms.find(atom => atom.type === 'ftyp')
    const moovAtom = atoms.find(atom => atom.type === 'moov')
    const mdatAtom = atoms.find(atom => atom.type === 'mdat')

    if (!ftypAtom || !moovAtom) {
        throw new Error('缺少必要的 atoms')
    }

    // 计算偏移量变化
    const otherAtoms = atoms.filter(atom => 
        atom.type !== 'ftyp' && atom.type !== 'moov'
    )

    const oldMdatOffset = mdatAtom ? mdatAtom.offset : 0
    const atomsBeforeMdat = otherAtoms.filter(a => 
        mdatAtom && a.offset < mdatAtom.offset
    )
    
    const sizeBeforeMdat = atomsBeforeMdat.reduce((sum, a) => sum + a.size, 0)
    const newMdatOffset = ftypAtom.size + moovAtom.size + sizeBeforeMdat
    const offsetDelta = newMdatOffset - oldMdatOffset

    console.log('重排序信息:', {
        oldMdatOffset,
        newMdatOffset,
        offsetDelta
    })

    // 修复 moov 中的偏移量
    const fixedMoovData = new Uint8Array(moovAtom.data)
    if (offsetDelta !== 0) {
        updateChunkOffsets(fixedMoovData, 0, fixedMoovData.length, offsetDelta)
    }

    // 重新组装
    const totalLength = originalBuffer.length
    const result = new Uint8Array(totalLength)
    let writeOffset = 0

    // 1. ftyp
    result.set(ftypAtom.data, writeOffset)
    writeOffset += ftypAtom.size

    // 2. moov (已修复)
    result.set(fixedMoovData, writeOffset)
    writeOffset += moovAtom.size

    // 3. 其他 atoms
    otherAtoms.forEach(atom => {
        result.set(atom.data, writeOffset)
        writeOffset += atom.size
    })

    console.log(`写入完成: ${writeOffset} / ${totalLength} bytes`)

    return result
}

/**
 * 更新 chunk offsets
 */
function updateChunkOffsets(buffer, start, end, offsetDelta) {
    let offset = start

    while (offset < end - 8) {
        const size = ((buffer[offset] & 0xFF) << 24) | 
                     ((buffer[offset + 1] & 0xFF) << 16) | 
                     ((buffer[offset + 2] & 0xFF) << 8) | 
                     (buffer[offset + 3] & 0xFF)
        
        const type = String.fromCharCode(
            buffer[offset + 4],
            buffer[offset + 5],
            buffer[offset + 6],
            buffer[offset + 7]
        )

        if (size < 8 || offset + size > end) break

        if (type === 'stco') {
            const entryCount = ((buffer[offset + 12] & 0xFF) << 24) | 
                              ((buffer[offset + 13] & 0xFF) << 16) | 
                              ((buffer[offset + 14] & 0xFF) << 8) | 
                              (buffer[offset + 15] & 0xFF)
            
            for (let i = 0; i < entryCount; i++) {
                const offsetPos = offset + 16 + (i * 4)
                let chunkOffset = ((buffer[offsetPos] & 0xFF) << 24) | 
                                 ((buffer[offsetPos + 1] & 0xFF) << 16) | 
                                 ((buffer[offsetPos + 2] & 0xFF) << 8) | 
                                 (buffer[offsetPos + 3] & 0xFF)
                
                chunkOffset = (chunkOffset >>> 0) + offsetDelta
                
                buffer[offsetPos] = (chunkOffset >>> 24) & 0xFF
                buffer[offsetPos + 1] = (chunkOffset >>> 16) & 0xFF
                buffer[offsetPos + 2] = (chunkOffset >>> 8) & 0xFF
                buffer[offsetPos + 3] = chunkOffset & 0xFF
            }
        } else if (['moov', 'trak', 'mdia', 'minf', 'stbl'].includes(type)) {
            updateChunkOffsets(buffer, offset + 8, offset + size, offsetDelta)
        }

        offset += size
    }
}
